Modifying the BranchLabel Combobox

Eddie's Lessons, version 5

level: beginner

by Alyce Watson [http://alycesrestaurant.com/]

Home

Tip Corner

Youth Corner

Stylebits Corner

Custom Cursors

LB Wire Frame Lib

Random Numbers

Eddie Version 5

Page Orientation

Help

Index


What is Eddie?

Eddie is a new code editor written in Liberty BASIC, for Liberty BASIC. Eddie can be customized and extended to meet the needs of the individual programmer. The newest version is available here: Eddie v5


A neat trick with the combobox!

In Eddie v4, we added a combobox that held the branch labels, sub definitions and function definitions. When the user selects one of these from the combobox, the texteditor scrolls that line to the top. The original way worked perfectly, but we promised an even better way, and here it is!

When we fill the combobox, we'll add a large number of blank spaces, and then we'll append the line number that contains the branch label. Since there are so many spaces between the line text and the appended line number, the user cannot see the line number, but we can use it in the program. We no longer need to loop through the contents of the texteditor, looking for a match for the text in the selected combobox item.

To insure that the user cannot see the line number, we disable the combobox's ability to scroll past the visible text area with a stylebits command:

stylebits #1.c, 0,_CBS_AUTOHSCROLL,0,0

For more on combobox stylebits, see the Stylebits Corner this month, written by Janet Terra. Thanks for the great tips, Janet!

Filling the branch label combobox

Part of the routine to fill the combobox with text for the branch labels, sub definitions and function definitions stays the same. We still loop through each line to see if it begins with a left bracket, the word "function" or the word "sub." The change comes when we add the line as an item to our combobox. We add it as usual, then append 300 blank spaces, and the string representation of the line number. The variable 'bx' is the item count in the combobox, and is incremented each time we find a branch label to add. Since the variable 'i' corresponds to the line number as we loop through the lines, the new code looks like this:

branch$(bx)=Trim$(line$) + space$(300) + str$(i)

The entire routine to add branch labels to the combobox, along with their corresponding line numbers is below.

[fillBranch]
    timer 0
    #1.te "!lines rowcount"
    #1.te "!origin? col row"

    REDIM branch$(rowcount)
    branch$(1)="<start>"  + space$(300) + "1"

    'fill combobox with labels, functions and sub definitions
    'pad with 300 spaces, then add line number
    bx=2
    For i=1 to rowcount
        #1.te,"!line ";i;" line$";
            If Left$(Trim$(line$),1)="[" Then
                branch$(bx)=Trim$(line$) + space$(300) + str$(i)
                bx=bx+1
            End If
            If Lower$(Word$(line$,1))="function" Then
                branch$(bx)=Trim$(line$) + space$(300) + str$(i)
                bx=bx+1
            End If
            If Lower$(Word$(line$,1))="sub" Then
                branch$(bx)=Trim$(line$) + space$(300) + str$(i)
                bx=bx+1
            End If
    Next i

    #1.c "reload"
    #1.c "selectindex 1";
    TIMER 50, [activateTimer]
    return

Don't forget the start!

We added a special item called "<start>" as the first item in the combobox, so that the user can easily get back to the top of the code. When we add this item, we must now add the number '1' to the end of it, just as we add line numbers to the ends of the branch labels. Here's the code:

branch$(1)="<start>"  + space$(300) + "1"

Extracting the line number from the combobox item.

It's really easy to extract the line number after the user has selected an item in the combobox. The code to extract the text in the combobox selection looks like this:

#1.c "selection? branchselect$"

We simply place the rightmost 6 characters from the selected item into a variable with the RIGHT$() string function.

ln$ = right$(branchselect$, 6)

To retrieve the line number from this text, we use the Liberty BASIC VAL() function, like this:

linenumber = val(ln$)

Once we have the line number, we use the !ORIGIN command to scroll that line to the top of the texteditor. Here it is:

#1.te "!origin 1 ";linenumber

The entire routine looks like this:

[chooseBranch]
   '** CHOOSE BRANCH, SET EDITOR TO THAT POSITION
    timer 0
    #1.c "selection? branchselect$"
    
    'get the text at the end of the item
    ln$ = right$(branchselect$, 6)
    
    'get value of text, which will = linenumber
    linenumber = val(ln$)
    
    'now scroll texteditor so that line is at top
    #1.te "!origin 1 ";linenumber
    #1.te "!setfocus"
    TIMER 50, [activateTimer]
    Wait

Eddie v5

Here is the code for Eddie v5.

'** Eddie - an LB Code Editor
    'version 5
    'modifies branch label combobox

if val(Version$)<4.02 then
    notice "For Liberty BASIC v4.02 and higher."
    'the *!origin* command in LB4.02 has designator vars in this order - col then row
    'in LB4.01 the order was row then col
    'also - in LB4.01 the *!origin?* command was broken and the row receiver var didn't get filled
    end
end if

[VariableSetup]
    '#f will be the handle for opening files
    'note that Version$ is a reserved variable name
    EddieVersion$ = "5"
    'path to Liberty.exe for running programs:
    LibertyExe$ = ""
    'name of ini file for this version of Eddie
    IniFile$ = "eddie4.ini"
    'variable to hold contents of texteditor
    text$ = ""
    'filename for writing a temp file to disk
    tempfile$ = DefaultDir$ + "\tempfile.bas"
    'filename for user saving file to disk
    savefile$ = ""

    dim branch$(1000)       'array to hold branch labels
    branch$(1) = "<start>"  'first designation takes you to top of code

[WindowSetup]
    NOMAINWIN
    WindowWidth = 600 : WindowHeight = 360
    UpperLeftX = INT((DisplayWidth-WindowWidth)/2)
    UpperLeftY = INT((DisplayHeight-WindowHeight)/2)

[ControlSetup]
'menus
Menu        #1, "&File", "&New", [new], "&Open", [open], "&Save", [save],_
            |,"&Print", [print], "E&xit", [quit]

'LB will place Edit menu where you specify in list of menus
'do not use ampersand & in Edit menu caption
Menu        #1, "Edit"
Menu        #1, "&Run","R&un", [run]
Menu        #1, "&Tools", "&Go to Line", [gotoLine]
Menu        #1, "&Help", "He&lp", [help], "&About", [about]

'buttons for a toolbar lookalike
button      #1.new, "New",[new],UL, 0, 0, 45, 20
button      #1.open, "Open",[open],UL, 45, 0, 45, 20
button      #1.save, "Save",[save],UL, 90, 0, 45, 20
button      #1.print, "Print",[print],UL, 135, 0, 45, 20
button      #1.cut, "Cut",[cut],UL, 190, 0, 45, 20
button      #1.copy, "Copy",[copy],UL, 235, 0, 45, 20
button      #1.paste, "Paste",[paste],UL, 280, 0, 45, 20
button      #1.run, "Run",[run],UL, 335, 0, 45, 20
button      #1.help, "Help",[help],UL, 380, 0, 45, 20

'a graphicbox for line numbers
stylebits #1.g, 0,_WS_BORDER,0,0
graphicbox  #1.g, 0, 52, 39, 230
'a texteditor
texteditor  #1.te, 39, 52, 545, 250

'combobox for branch labels
stylebits #1.c, 0,_CBS_AUTOHSCROLL,0,0
combobox #1.c, branch$(),[chooseBranch],40,22,385,300

Open "Eddie - an LB Code Editor v." + EddieVersion$ for Window as #1
    'trap the close event, if the user closes the
    'window with the X button
    #1 "trapclose [quit]"

    'set the font for the window and controls
    #1 "font ms_sans_serif 10"

    'set a custom font for the texteditor
    #1.te "!font courier_new 0 16"
    'set up the graphicbox
    #1.g "down; fill Buttonface; backcolor buttonface; flush"
    'use the same font as the texteditor
    #1.g "font courier_new 0 16"
    #1.g "autoresize"

    'cause the texteditor to resize automatically
    'when the user resizes the window
    #1.te "!autoresize"

    'select item in combobox
    #1.c "selectindex 1"

    TIMER 50, [activateTimer]    'initialize the timer

[loop]
    Wait

[quit]
    TIMER 0
    close #1 : END

[activateTimer]
    'check the number of lines of text
    #1.te "!lines rowcount"
    'if it has changed, refill branch label combobox
    if rowcount<>lastRowcount then gosub [fillBranch]
    'new lastRowcount is this rowcount
    lastRowcount=rowcount

    'check the number of the row at the top of the texteditor
     #1.te "!origin? col row"
     'if it is the same as last check, do nothing
     if row = lastRow then wait
    'turn off timer for this routine
     TIMER 0
     'new lastRow is current row, for next check
     lastRow = row
     'delete previously named drawing segment called *linenums*
     #1.g "delsegment linenums"
     'location to start drawing line numbers
     #1.g "place 2 14"
     'fill with default buttonface color to erase previous line numbers
     #1.g "fill buttonface"
     'use top row number as starting number for line numbers
     for i = row to row+100
        'using() aligns the numbers for us
         num$=using("####",i)
         #1.g "\";num$
     next
     'flush and give this segment the name *linenums*
     #1.g "flush linenums"
     'start timer again
     TIMER 50, [activateTimer]
     wait

[new]
    #1.te "!CLS"
    Wait

[open]
    TIMER 0
    filedialog "Open","*.bas",openfile$
    if openfile$="" then wait

    open openfile$ for input as #f
    'dump contents of file into texteditor
    #1.te "!contents #f"
    close #f
    gosub [fillBranch]
    TIMER 50, [activateTimer]
    Wait

[save]
    TIMER 0
    'if the word SAVE is in the caption, LB
    'automatically creates a SAVE dialog
    filedialog "Save As","*.bas",savefile$
    if savefile$="" then wait

    'make sure that user had given the file a *bas extension
    if right$(lower$(savefile$),4)<>".bas" then
        savefile$=savefile$+".bas"
    end if

    'get contents of texteditor into string variable
    #1.te "!contents? text$"
    if text$="" then
        notice "No file to save."
        wait
    end if

    'open file and write text to it
    open savefile$ for output as #f
        #f text$
    close #f
    TIMER 50, [activateTimer]
    Wait

[print]
    TIMER 0
    'get contents of texteditor into string variable
    #1.te "!contents? text$"
    if text$="" then
        notice "No text to print."
        wait
    end if

    'send text to printer
    lprint text$
    'cause printing to happen now
    dump
    TIMER 50, [activateTimer]
    Wait

[help]
    'place code here
    Wait

[about]
    'place code here
    Wait

[cut]
    #1.te "!cut"
    wait

[copy]
    #1.te "!copy"
    wait

[paste]
    #1.te "!paste"
    wait

[run]
    TIMER 0
    'go to routine to get liberty.exe path
    'into variable LibertyExe$$
    gosub [GetLibertyPath]
    'if we can't find the path to Liberty BASIC
    'we must abort the RUN operation
    if LibertyExe$="" then wait

    'get contents of texteditor into string variable
    #1.te "!contents? text$"
    'if there is no code, then abort the RUN operation
    if text$="" then
        notice "No code to run."
        wait
    end if

    'open file and write text to it
    open tempfile$ for output as #f
        print #f, text$
    close #f

    'use RUN command to run Liberty BASIC
    'with this file loaded
    'put filename in quotation marks, so
    'that spaces do not break up the filename
    RUN LibertyExe$ + " " + chr$(34) + tempfile$ + chr$(34)
    TIMER 50, [activateTimer]
    wait

[GetLibertyPath]
    timer 0
    'file to store path info is IniFile$
    'open for append to see if file exists
    'attempting to open a nonexistent file for INPUT causes an error
    open IniFile$ for append as #f
    lenFile = LOF(#f)
    close #f

    'if the length = 0, the file doesn't exist
    if lenFile=0 then
        filedialog "Find Liberty.exe","*liberty*.exe",LibertyExe$
        if LibertyExe$="" then
            'the user cancelled the filedialog
            notice "Liberty.exe not found."
        else
            'the user selected liberty.exe on his computer
            'open the ini file and store the information
            open IniFile$ for output as #f
            print #f, LibertyExe$
            close #f
        end if
    else
        'if the length is greater than 0, the file exists
        'open it for input and read the first line
        'into the variable LibertyExe$
        open IniFile$ for input as #f
        line input #f, LibertyExe$
        close #f
    end if
    TIMER 50, [activateTimer]
    RETURN

[fillBranch]
    timer 0
    #1.te "!lines rowcount"
    #1.te "!origin? col row"

    REDIM branch$(rowcount)
    branch$(1)="<start>"  + space$(300) + "1"

    'fill combobox with labels, functions and sub definitions
    'pad with 300 spaces, then add line number
    bx=2
    For i=1 to rowcount
        #1.te,"!line ";i;" line$";
            If Left$(Trim$(line$),1)="[" Then
                branch$(bx)=Trim$(line$) + space$(300) + str$(i)
                bx=bx+1
            End If
            If Lower$(Word$(line$,1))="function" Then
                branch$(bx)=Trim$(line$) + space$(300) + str$(i)
                bx=bx+1
            End If
            If Lower$(Word$(line$,1))="sub" Then
                branch$(bx)=Trim$(line$) + space$(300) + str$(i)
                bx=bx+1
            End If
    Next i

    #1.c "reload"
    #1.c "selectindex 1";
    TIMER 50, [activateTimer]
    return


[chooseBranch]
   '** CHOOSE BRANCH, SET EDITOR TO THAT POSITION
    timer 0
    #1.c "selection? branchselect$"
    
    'get the text at the end of the item
    ln$ = right$(branchselect$, 6)
    
    'get value of text, which will = linenumber
    linenumber = val(ln$)
    
    'now scroll texteditor so that line is at top
    #1.te "!origin 1 ";linenumber
    #1.te "!setfocus"
    TIMER 50, [activateTimer]
    Wait
  
  [gotoLine]
    timer 0
    #1.te "!lines rowcount"
    gotoLine=rowcount
    msg$="Go to line? Max is ";gotoLine
    prompt msg$;gotoLine
    if gotoLine>rowcount then gotoLine=rowcount
    if gotoLine<1 then gotoLine=1
    #1.te "!origin 1 ";gotoLine
    #1.te "!setfocus"
    TIMER 50, [activateTimer]
    wait


Home

Tip Corner

Youth Corner

Stylebits Corner

Custom Cursors

LB Wire Frame Lib

Random Numbers

Eddie Version 5

Page Orientation

Help

Index